/**
 * @author zs.duan
 * @date 2024-08-30
 * @description 用户相关接口 v2 版本
 * */
const express = require("express");
const cookie = require('cookie');
const router = express.Router();
const Db = require("../../utils/db");
const createSql = require("../../utils/Create_SQL");
const { errorCode, successCode, config } = require('../../config/config');
const utils = require("../../utils/utils.js");

/**
 * @swagger
 * /api/v2/users/adminLogin:
 *    post:
 *      tags:
 *      - 用户相关
 *      summary: 用户登录-后台
 *      produces:
 *      - application/json
 *      requestBody:
 *        description: Optional description in *Markdown*
 *        required: true
 *        content:
 *          application/json:
 *            schema:
 *              type: object
 *              properties:
 *                user:
 *                  type: string
 *                  description: 加密后的用户名和密码以及是否扫码登录
 *                password:
 *                  type: string
 *                  description: 加密后的验证码
 *                code:
 *                  type: string
 *                  description: 未加密验证码
 *                ua:
 *                  type: string
 *                  description: 设备信息
 *      responses:
 *        200:
 *          description: 返回结果
 * */
router.post("/adminLogin", async (req, res) => {
    let { user, password, code, ua } = req.body;
    if (!user || !password) {
        res.status(500);
        return res.send({
            ...errorCode[10003]
        })
    }
    res.clearCookie('token');
    // 验证验证码
    if (code != utils.ACEdecrypt({ word: password })) {
        res.status(500);
        return res.send({
            ...errorCode[10016]
        })
    }
    if (!ua) {
        res.status(500);
        return res.send({
            ...errorCode[10000],
            message: "未知设备,无法登录"
        })
    }

    let loginInfo = utils.ACEdecrypt({ word: user, type: "object" });
    loginInfo.password = utils.MD5({ word: loginInfo.password });
    let sql = createSql.select().from("user_admin").where(`user_name = '${loginInfo.username}' or email = '${loginInfo.username}'  and password = '${loginInfo.password}'`).build();
    let reslut = await Db.query(sql, res);
    if (reslut.code > 200) return;
    if (reslut.length == 0) {
        res.status(500);
        return res.send({
            ...errorCode[10012]
        })
    }
    let userInfo = reslut[0];
    if (userInfo.is_disable != '0') {
        res.status(500);
        return res.send({
            ...errorCode[10010],
            message: "该用户已被禁用"
        })
    }
    let { loginIP, token, ID } = userInfo;
    let tokenJson = { ID: ID };
    let ip = utils.getClientIP(req);
    token = utils.GenerateSecretKey(tokenJson, config.secretOrPrivateKey);
    let updateSql = createSql.update("user_admin").set({ loginIP: ip, ua: JSON.stringify(ua), token: token, lastLoginTime: utils.getTime("yyyy-MM-dd HH:mm:ss") }).where(`ID = '${ID}'`).build();
    let updateReslut = await Db.query(updateSql, res);
    if (updateReslut.code > 200) return;

    const serialized = cookie.serialize('token', token, {
        maxAge: 1000 * 60 * 60 * 24 * 5,
        httpOnly: true,
        secure: true,
        sameSite: 'none',
        path: '/'
    });
    res.setHeader('Set-Cookie', serialized);
    res.json({
        ...successCode[200],
        data: {
            token: token,
        }
    })
})

/**
 * @swagger
 * /api/v2/users/adminLoginByCode:
 *    post:
 *      tags:
 *      - 用户相关
 *      summary: 用户验证码登录-后台
 *      produces:
 *      - application/json
 *      requestBody:
 *        description: Optional description in *Markdown*
 *        required: true
 *        content:
 *          application/json:
 *            schema:
 *              type: object
 *              properties:
 *                email:
 *                  type: string
 *                  description: 邮箱
 *                code:
 *                  type: string
 *                  description: 验证码
 *                ua:
 *                  type: string
 *                  description: 设备信息
 *      responses:
 *        200:
 *          description: 返回结果
 * */
router.post("/adminLoginByCode", async (req, res) => {
    let { email, code, ua } = req.body;
    if (!email || !code) {
        res.status(500);
        return res.send({
            ...errorCode[10003]
        })
    }
    res.clearCookie('token');
    let sql = createSql.select().from("code_expires")
        .where(`name = '${email}'`)
        .and(`code = '${code}'`)
        .and(`isExpire = 0`)
        .and(`type = 'admin'`)
        .build();
    let reslut = await Db.query(sql, res);
    if (reslut.code > 200) return;
    if (reslut.length == 0) {
        res.status(500);
        return res.send({
            ...errorCode[10016],
            message: "验证码错误/用户不存在"
        })
    }
    let codeInfo = reslut[0];
    if (new Date().getTime() > codeInfo.expires) {
        res.status(500);
        return res.send({
            ...errorCode[10016],
            message: "验证码已过期"
        })
    }
    sql = createSql.update("code_expires").set({ isExpire: 1 }).where(`ID = '${codeInfo.ID}'`).build();
    await Db.query(sql, res);
    sql = createSql.select().from("user_admin").where(`email = '${email}'`).build();
    reslut = await Db.query(sql, res);
    if (reslut.code > 200) return;
    if (reslut.length == 0) {
        res.status(500);
        return res.send({
            ...errorCode[10012]
        })
    }
    let userInfo = reslut[0];
    if (userInfo.is_disable != '0') {
        res.status(500);
        return res.send({
            ...errorCode[10010],
            message: "该用户已被禁用"
        })
    }
    let { loginIP, token, ID } = userInfo;
    let tokenJson = { ID: ID };
    let ip = utils.getClientIP(req);
    token = utils.GenerateSecretKey(tokenJson, config.secretOrPrivateKey);
    let updateSql = createSql.update("user_admin").set({ loginIP: ip, ua: JSON.stringify(ua), token: token, lastLoginTime: utils.getTime("yyyy-MM-dd HH:mm:ss") }).where(`ID = '${ID}'`).build();
    let updateReslut = await Db.query(updateSql, res);
    if (updateReslut.code > 200) return;
    res.cookie('token', token, { maxAge: 1000 * 60 * 60 * 24 * 1, httpOnly: true });
    return res.json({
        ...successCode[200],
        data: {
            token: token,
        }
    })
})


/**
 * @swagger
 * /api/v2/users/adminLoginOut:
 *    post:
 *      tags:
 *      - 用户相关
 *      summary: 退出登录 后台
 *      responses:
 *        200:
 *          description: 返回结果
 * */
router.post("/adminLoginOut", async (req, res) => {
    res.clearCookie('token');
    res.clearCookie("userInfo")
    return res.json({
        ...successCode[200],
        data: {}
    })
})

/**
 * @swagger
 * /api/v2/user/scanAdminLogin:
 *    post:
 *      tags:
 *      - 用户相关
 *      summary: 扫码登录-后台
 *      produces:
 *      - application/json
 *      requestBody:
 *        description: Optional description in *Markdown*
 *        required: true
 *        content:
 *          application/json:
 *            schema:
 *              type: object
 *              properties:
 *                userInfo:
 *                  type: object
 *                  description: 加密后的验证码
 *                code:
 *                  type: string
 *                  description: 扫码的code
 *      responses:
 *        200:
 *          description: 返回结果
 * */

router.post("/scanAdminLogin", async (req, res) => {

})

/**
 * @swagger
 * /api/v2/users/getScanLoginResult:
 *    post:
 *      tags:
 *      - 用户相关
 *      summary: 扫码登录状态-查询
 *      produces:
 *      - application/json
 *      requestBody:
 *        description: Optional description in *Markdown*
 *        required: true
 *        content:
 *          application/json:
 *            schema:
 *              type: object
 *              properties:
 *                code:
 *                  type: string
 *                  description: 扫码的code
 *      responses:
 *        200:
 *          description: 返回结果
 * */

router.post("/getScanLoginResult", async (req, res) => {
    const { code } = req.body;
    if (!code) {
        res.status(500);
        return res.json({
            ...errorCode[10003]
        })
    }
    // 查询二维码是否被扫描
    let sql = createSql.select().from("scan_login_info").where(`code = '${code}'`).end();
    let data = await Db.query(sql, res);
    if (data.code) return;
    if (!data.length) {
        return res.json({
            ...successCode[200],
            message: "用户未扫码",
            type: "0"
        })
    }
    data = data[0];
    if (data.is_expired == '1') {
        res.status(200);
        return res.json({
            ...errorCode[10002],
            message: "二维码已过期",
            type : "-1"
        })
    }
    sql = createSql.update("scan_login_info").set({ is_expired: "1" }).where(`code = '${data.code}'`).end();
    await Db.query(sql, res);
    let { userInfo } = data;
    userInfo = JSON.parse(userInfo);
    let tokenJson = { ID: userInfo.ID };
    let ip = utils.getClientIP(req);
    token = utils.GenerateSecretKey(tokenJson, config.secretOrPrivateKey);
    let updateSql = createSql.update("user_admin").set({ loginIP: ip, ua: JSON.stringify({type : "扫描登录"}), token: token, lastLoginTime: utils.getTime("yyyy-MM-dd HH:mm:ss") }).where(`ID = '${userInfo.ID}'`).build();
    let updateReslut = await Db.query(updateSql, res);
    if (updateReslut.code > 200) return;
    const serialized = cookie.serialize('token', token, {
        maxAge: 1000 * 60 * 60 * 24 * 5,
        httpOnly: true,
        secure: true,
        sameSite: 'none',
        path: '/'
    });
    res.setHeader('Set-Cookie', serialized);
    return res.json({
        ...successCode[200],
        data: {
            token: token,
        },
        type : 1
    })
})


/**
 * @swagger
 * /api/v2/users/getUserInfo:
 *    post:
 *      tags:
 *      - 用户相关
 *      summary: 根据token获取用户信息
 *      responses:
 *        200:
 *          description: 返回结果
 * */
router.post("/getUserInfoByAdmin", async (req, res) => {
    let loginInfo = {};
    try {
        loginInfo = await utils.isLogin(req, res)
    } catch (e) {
        loginInfo = {};
    }
    if (!loginInfo.code) return;
    let sql = createSql.select().from("user_admin").where(`ID = '${loginInfo.data.ID}'`).build();
    let reslut = await Db.query(sql, res);
    if (reslut.code > 200) return;
    let userInfo = reslut[0];
    const { user_name, ID, role_ID, is_disable, is_del } = userInfo;
    let menu_ID_sql = createSql.select('menu_ID').from('admin_menu_by_roles').where(`role_ID = '${role_ID}'`).build();
    let menusSql = createSql.select().from('admin_new_menu').where('is_del != 1 AND is_show = 1 AND ID').in(
        `(${menu_ID_sql})`
    ).build();
    let ruleSql = createSql.select().from('admin_menu_by_roles').where(`role_ID = '${role_ID}'`).build();
    let menusReslut = await Db.query(menusSql, res);
    let ruleReslut = await Db.query(ruleSql, res);
    let rules = [];
    ruleReslut.forEach(item => {
        let index = menusReslut.findIndex(menuItem => {
            return item.menu_ID == menuItem.ID
        });
        item.actions = item.actions.split(",");
        rules.push({
            ...item,
            path: index != -1 ? menusReslut[index].path : ''
        })
    })
    rules = utils.formatDateByArray(rules, ['createdtime', 'updatetime']);

    menusReslut = utils.deleteArrayObject(menusReslut, ["is_del"]);
    menusReslut = utils.formatDateByArray(menusReslut, ["createdtime", "updatetime"]);
    menusReslut = utils.formatNumberToBoolean(menusReslut, ["hidden", "is_keep_alive", "affix", "is_show"]);
    let ParentMenu = [];
    menusReslut.forEach(item => {
        item.meta = item.meta ? JSON.parse(item.meta) : {};
        item.meta.title = item.title;
        item.meta.icon = item.icon;
        item.meta.roles = rules.filter(ruleItem => ruleItem.menu_ID == item.ID)[0].actions;
        item.meta.affix = item.affix;
        item.isKeepAlive = item.is_keep_alive;
        if (item.type == 1) {
            ParentMenu.push({
                ...item,
                children: []
            })
        }
    });
    menusReslut.forEach(item => {
        let parent = ParentMenu.filter(parentItem => parentItem.ID == item.parent_ID);
        if (parent.length) {
            parent[0].children.push(item);
            parent[0].children.sort((a, b) => a.sorts - b.sorts)
        }
    });
    ParentMenu.sort((a, b) => a.sorts - b.sorts);
    if (is_del == '1') {
        res.status(500);
        res.clearCookie('token');
        return res.send({
            ...errorCode[10010],
            message: "该用户不存在"
        })
    }
    if (is_disable == '1') {
        res.status(500);
        res.clearCookie('token');
        return res.send({
            ...errorCode[10010],
            message: "该用户已被禁用"
        })
    }
    const sendData = {
        username: user_name,
        email: userInfo.email,
        ID,
        role_ID,
        menu: ParentMenu,
        rules: rules
    }
    return res.json({
        ...successCode[200],
        data: {
            data : sendData ,
            userInfo : { username: user_name, email: userInfo.email, ID, role_ID, }
        }
    })
})

module.exports = router;
